<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>12.2组件状态自更新</title>
</head>
<body>
  <div id="app"></div>
  
<script type="module">

import {createRenderer} from '../3.renderer/createRenderer.js'
import {reactive} from '../2.observer/reactive.js'
import {effect} from '../2.observer/effect.js'
const myComponent = {
  name: 'myComponent',
  data() {
    return {
      foo: 'hello world'
    }
  },
  beforeCreate() {
    console.log('beforeCreate')
  },
  created() {
    console.log(this, 'created')
    this.foo = 'created'
  },
  beforeMount() {
    console.log(document.getElementById('test'), this, 'beforeMount')
  },
  mounted() {
    console.log(document.getElementById('test'), this, 'mounted')
  },
  beforeUpdate() {
    console.log(this, 'beforeUpdate')
  },
  updated() {
    console.log(this, 'updated')
  },
  render() {
    return {
      type: 'div',
      props:{
        id:'test',
        onClick:() => {
          this.foo = 'hi'
        }
      },
      children: `foo 的值是 ${this.foo}`
    }
  }
}

//组件vnode
const vnode = {
  type: myComponent
}
function debuggerMountComponent(patch) {
  return function mountComponent (vnode, container, anchor) {
    const componentOptions = vnode.type
    const {render, data, beforeCreate, created, beforeMount, mounted, beforeUpdate, updated} = componentOptions
    beforeCreate?.()
    const state = reactive(data())
    //组件实例
    const instance = {
      state,
      isMounted: false,
      subTree: null
    }
    vnode.component = instance
    created?.call(state)
    effect(()=> {
      const subTree = render.call(state, state)
      if(!instance.isMounted) {
        beforeMount?.call(state)
        patch(null, subTree, container, anchor)
        instance.isMounted = true
        mounted?.call(state)
      } else {
        beforeUpdate?.call(state)
        patch(instance.subTree, subTree, container, anchor)
        updated?.call(state)
      }
      instance.subTree = subTree
    }) 
  }
}

const render = createRenderer({debuggerMountComponent})
render(vnode, document.getElementById('app'))
</script>
</body>

</html>